package com.cloud.adrian.novel.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cloud.adrian.novel.common.auth.JwtUtils;
import com.cloud.adrian.novel.common.auth.UserHolder;
import com.cloud.adrian.novel.common.constant.DatabaseConstants;
import com.cloud.adrian.novel.common.constant.ErrorCodeEnum;
import com.cloud.adrian.novel.common.constant.SystemConfigConstants;
import com.cloud.adrian.novel.common.req.PageReqDto;
import com.cloud.adrian.novel.common.resp.PageRespDto;
import com.cloud.adrian.novel.common.resp.RestResp;
import com.cloud.adrian.novel.config.exception.BusinessException;
import com.cloud.adrian.novel.user.dao.entity.UserComment;
import com.cloud.adrian.novel.user.dao.entity.UserInfo;
import com.cloud.adrian.novel.user.dao.mapper.UserCommentMapper;
import com.cloud.adrian.novel.user.dao.mapper.UserInfoMapper;
import com.cloud.adrian.novel.user.dto.req.UserLoginReqDto;
import com.cloud.adrian.novel.user.dto.req.UserRegisterReqDto;
import com.cloud.adrian.novel.user.dto.resp.UserCommentRespDto;
import com.cloud.adrian.novel.user.dto.resp.UserInfoRespDto;
import com.cloud.adrian.novel.user.dto.resp.UserLoginRespDto;
import com.cloud.adrian.novel.user.dto.resp.UserRegisterRespDto;
import com.cloud.adrian.novel.user.manager.redis.VerifyCodeManager;
import com.cloud.adrian.novel.user.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * 用户模块 服务实现类
 * @Author: xiangguiliang
 * @version: 1.0
 * @since: 2024/05/17
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final VerifyCodeManager verifyCodeManager;

    private final UserInfoMapper userInfoMapper;

    private final UserCommentMapper userCommentMapper;

    @Override
    public RestResp<List<UserInfoRespDto>> listUserInfoByIds(List<Long> userIds) {
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.in(DatabaseConstants.CommonColumnEnum.ID.getName(), userIds);
        return RestResp.ok(userInfoMapper.selectList(queryWrapper).stream().map(v ->
                UserInfoRespDto.builder()
                        .id(v.getId())
                        .username(v.getUsername())
                        .userPhoto(v.getUserPhoto())
                        .build()).toList());
    }

    @Override
    public RestResp<UserRegisterRespDto> register(UserRegisterReqDto dto) {
        // 校验验证码是否正确
        if (!verifyCodeManager.imgVerifyCodeOk(dto.getSessionId(), dto.getVelCode())) {
            // 验证码错误，校验失败
            throw new BusinessException(ErrorCodeEnum.USER_VERIFY_CODE_ERROR);
        }
        // 判断手机号是否已经注册
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(DatabaseConstants.UserInfoTable.COLUMN_USERNAME, dto.getUsername())
                .last(DatabaseConstants.SqlEnum.LIMIT_1.getSql());
        if (userInfoMapper.selectCount(queryWrapper) > 0) {
            // 手机号已经注册，校验失败
            throw new BusinessException(ErrorCodeEnum.USER_NAME_EXIST);
        }
        // 注册成功，保存用户信息
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername(dto.getUsername());
        // 加密密码
        userInfo.setPassword(DigestUtils.md5DigestAsHex(
                dto.getPassword().getBytes(StandardCharsets.UTF_8)));
        userInfo.setNickName(dto.getUsername());
        userInfo.setCreateTime(LocalDateTime.now());
        userInfo.setUpdateTime(LocalDateTime.now());
        userInfo.setSalt("0");
        userInfoMapper.insert(userInfo);

        // 删除验证码
        verifyCodeManager.removeImgVerifyCode(dto.getSessionId());

        // 生成jwt并返回
        return RestResp.ok(
            UserRegisterRespDto.builder()
                    .token(JwtUtils.generateToken(userInfo.getId(), SystemConfigConstants.NOVEL_FRONT_KEY))
                    .uid(userInfo.getId())
                    .build()
        );
    }

    @Override
    public RestResp<UserLoginRespDto> login(UserLoginReqDto dto) {
        // 查询用户信息
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(DatabaseConstants.UserInfoTable.COLUMN_USERNAME, dto.getUsername())
                .last(DatabaseConstants.SqlEnum.LIMIT_1.getSql());
        UserInfo userInfo = userInfoMapper.selectOne(queryWrapper);
        // 判断用户是否存在
        if (Objects.isNull(userInfo)) {
            // 用户不存在，校验失败
            throw new BusinessException(ErrorCodeEnum.USER_ACCOUNT_NOT_EXIST);
        }
        // 判断密码是否正确
        if (!Objects.equals(userInfo.getPassword(),
                DigestUtils.md5DigestAsHex(dto.getPassword().getBytes(StandardCharsets.UTF_8)))) {
            // 密码错误，校验失败
            throw new BusinessException(ErrorCodeEnum.USER_PASSWORD_ERROR);
        }
        // 生成jwt并返回
        return RestResp.ok(UserLoginRespDto.builder()
                        .token(JwtUtils.generateToken(userInfo.getId(), SystemConfigConstants.NOVEL_FRONT_KEY))
                        .uid(userInfo.getId())
                        .nickName(userInfo.getNickName()).build());
    }

    @Override
    public RestResp<UserInfoRespDto> getUserInfo(Long userId) {
        UserInfo userInfo = userInfoMapper.selectById(userId);
        return RestResp.ok(UserInfoRespDto.builder()
                .id(userId)
                .username(userInfo.getUsername())
                .userPhoto(userInfo.getUserPhoto())
                .userSex(userInfo.getUserSex())
                .nickName(userInfo.getNickName()).build());
    }

    @Override
    public RestResp<PageRespDto<UserCommentRespDto>> getUserComments(Long userId, PageReqDto dto) {
        dto.setPageSize(5);
        UserInfo userInfo = userInfoMapper.selectById(userId);
        Page<UserComment> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        QueryWrapper<UserComment> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(DatabaseConstants.BookCommentTable.COLUMN_USER_ID, userId);
        userCommentMapper.selectPage(page, queryWrapper);
        List<UserCommentRespDto> list = page.getRecords().stream().map(
                v -> UserCommentRespDto.builder()
                        .id(v.getId())
                        .commentContent(v.getCommentContent())
                        .commentTime(v.getCreateTime())
                        .commentUser(userInfo.getUsername())
                        .commentUserId(userInfo.getId())
                        .commentUserPhoto(userInfo.getUserPhoto())
                        .build()).toList();
        return RestResp.ok(PageRespDto.of(dto.getPageNum(), dto.getPageSize(), page.getTotal(), list));
    }

    @Override
    public RestResp<Void> updateUserInfo(UserInfo dto) {
        UserInfo userInfo = userInfoMapper.selectById(UserHolder.getUserId());
        userInfo.setUserPhoto(dto.getUserPhoto());
        userInfo.setUserSex(dto.getUserSex());
        userInfo.setUpdateTime(LocalDateTime.now());
        userInfo.setNickName(dto.getNickName());
        userInfoMapper.updateById(userInfo);
        return RestResp.ok();
    }
}
